package com.ruoyi.core.service.impl;

import cn.hutool.json.JSONUtil;

import com.ruoyi.common.constant.ErrorCode;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.core.judge.JudgeService;
import com.ruoyi.core.judge.codesandbox.CodeSandBox;
import com.ruoyi.core.judge.codesandbox.CodeSandBoxProxy;
import com.ruoyi.core.judge.codesandbox.CodeSandboxFactory;
import com.ruoyi.core.judge.codesandbox.model.ExecuteCodeRequest;
import com.ruoyi.core.judge.codesandbox.model.ExecuteCodeResponse;
import com.ruoyi.core.model.dto.questionsumbit.QuestionSubmitAddRequest;
import com.ruoyi.core.model.dto.question.JudgeCase;
import com.ruoyi.core.model.enums.QuestionSubmitLanguageEnum;
import com.ruoyi.core.model.enums.QuestionSubmitStatusEnum;
import com.ruoyi.core.service.QuestionSubmitService;
import com.ruoyi.question.domain.TQuestion;
import com.ruoyi.question.service.ITQuestionService;
import com.ruoyi.submit.domain.TQuestionSubmit;
import com.ruoyi.submit.service.ITQuestionSubmitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author wcc
 * @description 针对表【question_submit(题目提交)】的数据库操作Service实现
 */
@Service
public class QuestionSubmitServiceImpl implements QuestionSubmitService {

    @Resource
    private ITQuestionService questionService;


    @Autowired
    private ITQuestionSubmitService itQuestionSubmitService;

    @Autowired
    private JudgeService judgeService;


    /**
     * 提交题目
     *
     * @param questionSubmitAddRequest 请求包装类
     * @return 提交题目 id
     */
    @Override
    public AjaxResult doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest) {
        Long questionId = questionSubmitAddRequest.getQuestionId();
        String submitLanguage = questionSubmitAddRequest.getSubmitLanguage();
        String submitCode = questionSubmitAddRequest.getSubmitCode();
        // 校验编程语言是否正确
        QuestionSubmitLanguageEnum languageEnum = QuestionSubmitLanguageEnum.getEnumByValue(submitLanguage);
        if (languageEnum == null) {
            return  AjaxResult.error("编程语言错误");
        }
        // 判断实体是否存在，根据类别获取实体
        TQuestion tQuestion = questionService.selectTQuestionById(questionId);
        if (tQuestion == null) {
           return AjaxResult.error(ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 设置提交数
        Long submitNum = tQuestion.getSubmitNum();
        TQuestion updateQuestion = new TQuestion();
        synchronized (tQuestion.getSubmitNum()) {
            //请求次数累加
            submitNum = submitNum + 1;
            updateQuestion.setId(questionId);
            updateQuestion.setSubmitNum(submitNum);
            Integer save = questionService.updateTQuestion(updateQuestion);
            if ( save == 0 ) {
                return AjaxResult.error(ErrorCode.OPERATION_ERROR.getMessage());
            }
        }
        // 是否已提交题目
        long userId = SecurityUtils.getUserId();
        // 每个用户串行提交题目
        TQuestionSubmit questionSubmit = new TQuestionSubmit();
        // 用户id
        questionSubmit.setUserId(userId);
        // 题id
        questionSubmit.setQuestionId(questionId);
        // 题内容
        questionSubmit.setSubmitCode(submitCode);
        // 语言
        questionSubmit.setSubmitLanguage(submitLanguage);
        // 设置初始状态 0 等待中  1判题中   2成功   3失败
        questionSubmit.setSubmitState(QuestionSubmitStatusEnum.WAITING.getValue());
        // 判题信息
        questionSubmit.setJudgeInfo("{}");
        Integer save = itQuestionSubmitService.insertTQuestionSubmit(questionSubmit);
        if (save == 0){
           return AjaxResult.error( ErrorCode.SYSTEM_ERROR.getMessage());
        }
        Long questionSubmitId = questionSubmit.getId();
        // 执行判题服务
         CompletableFuture.runAsync(() -> {
             judgeService.doJudge(questionSubmitId);
         });

         //判题信息
        String judgeCaseStr = tQuestion.getJudgeCase();
        List<JudgeCase> judgeCasesList = JSONUtil.toList(judgeCaseStr, JudgeCase.class);
        // 调用沙箱，获取到执行结果
        CodeSandBox codeSandbox = CodeSandboxFactory.newInstance("remote");
        codeSandbox = new CodeSandBoxProxy(codeSandbox);
        // 通过Lambda表达式获取到每个题目的输入用例
        List<String> inputList = judgeCasesList.stream().map(JudgeCase::getInput).collect(Collectors.toList());
        // 调用沙箱
        ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder()
                .code(questionSubmitAddRequest.getSubmitCode())
                .language(questionSubmitAddRequest.getSubmitLanguage())
                .inputList(inputList)
                .build();
        ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);
        return AjaxResult.success(executeCodeResponse);
    }

}




